from tkinter import *
from tkinter import ttk, font, filedialog as fd
import shutil, os, ctypes, pyglet
from fractions import Fraction
from PIL import ImageTk, Image, ImageOps, ImageDraw, ImageFont
import Program
from Recipes_frame import Recipes_frame
from In_refrigerator_frame import In_refrigerator_frame
from In_cabinet_frame import In_cabinet_frame
from Edit_ingredient import Edit_ingredient
from Ingredient import Ingredient
from In_refrigerator import In_refrigerator
from In_cabinet import In_cabinet

class MyPantry(Frame):
    """
    Purpose:
        used as a frame to display and interact with ingredients and
        view what is in your refrigerator and cabinet
    Instance variables:
        self.label_title: label at the top of frame displaying "My Pantry"
        self.lower_frame: frame used to place buttons to switch between
            pantry and recipe frames
        self.my_pantry_tab_button: button to switch to my pantry frame
        self.recipes_tab_button: button to switch to recipes frame
        self.middle_frame: main frame that hold refrigerator and
            cabinet food information
        self.left_frame: frame for displaying refrigerator food information
        self.right_frame: frame for displaying cabinet food information
        self.refrigerator_food_label: label saying "Refrigerator Food"
        self.left_label_frame: frame for refrigerator food ingredients
        self.current_refrigerator_food_label_left: label for first column of
            refrigerator food ingredients
        self.current_refrigerator_food_label_right: label for second column of
            refrigerator food ingredients
        self.right_label_frame: frame for cabinet food ingredients
        self.cabinet_food_label: label saying "Cabinet Food"
        self.current_cabinet_food_label_left: label for first column of
            cabinet food ingredients
        self.current_cabinet_food_label_right: label for second column of
            cabinet food ingredients
        self.edit_ingredient_button: button that opens a frame to change the
            price of an ingredient
        self.ingredients_combo_box: combo box to select ingredient to edit
        self.ingredients_combo_box_clicked: bool containing if the
            combo box has been clicked
    Methods:
        change_colors: sets the frames colors to the provided hex colors
        ingredients_combo_box_clicked_event: runs when combo box has been clicked
        update_labels: updates the refrigerator and cabinet ingredients
            text to fit the screen
        edit_ingredient_clicked: handles the windows if the edit
            ingredient button is clicked
        update_combo_box_ingredients: sets the combo box values to
            ingredients that match search
    """

    def __init__(self, parent):
        Frame.__init__(self, parent)
        self.grid_columnconfigure(0, weight=1)
        self.grid_rowconfigure(0, weight=0)
        self.grid_rowconfigure(1, weight=1)
        self.grid_rowconfigure(2, weight=0)
        self.grid_rowconfigure(3, weight=0)
        self.grid_rowconfigure(4, weight=0)
        self.label_title = Label(
            self,
            text="My Pantry",
            font=Program.Program.resizing_title_font,
            borderwidth=1,
            relief="solid",
        )
        self.label_title.grid(row=0, column=0, pady=(10, 0), sticky="ew")

        self.lower_frame = Frame(self)
        self.lower_frame.grid(row=4, column=0, pady=(0, 20))
        self.my_pantry_tab_button = Button(
            self.lower_frame, text="My Pantry", state="disabled"
        )
        self.my_pantry_tab_button.grid(row=0, column=0, padx=(0, 5))
        self.recipes_tab_button = Button(
            self.lower_frame,
            text="Recipes",
            command=lambda: Program.Program.controller.change_frames(Recipes_frame),
        )
        self.recipes_tab_button.grid(row=0, column=1, padx=(5, 0))

        self.middle_frame = Frame(self)
        self.middle_frame.grid(row=1, column=0, pady=(10, 15), padx=20, sticky="nsew")
        self.middle_frame.rowconfigure(0, weight=1)
        self.middle_frame.columnconfigure(0, weight=1, uniform="equal")
        self.middle_frame.columnconfigure(1, weight=1, uniform="equal")
        self.left_frame = Frame(self.middle_frame, borderwidth=1, relief="solid")
        self.left_frame.grid(row=0, column=0, sticky="nsew", padx=(0, 15))
        self.left_frame.bind(
            "<Button-1>",
            lambda _: Program.Program.controller.change_frames(In_refrigerator_frame),
        )
        self.right_frame = Frame(self.middle_frame, borderwidth=1, relief="solid")
        self.right_frame.grid(row=0, column=1, sticky="nsew", padx=(15, 0))
        self.right_frame.bind(
            "<Button-1>", lambda _: Program.Program.controller.change_frames(In_cabinet_frame)
        )

        self.refrigerator_food_label = Label(
            self.left_frame,
            text="Refrigerator Food",
            font=Program.Program.resizing_title_font,
        )
        self.refrigerator_food_label.bind(
            "<Button-1>",
            lambda _: Program.Program.controller.change_frames(In_refrigerator_frame),
        )
        self.refrigerator_food_label.pack(fill="x")
        self.left_label_frame = Frame(self.left_frame)
        self.left_label_frame.pack(fill="both", expand=True)
        self.left_label_frame.bind(
            "<Button-1>",
            lambda _: Program.Program.controller.change_frames(In_refrigerator_frame),
        )
        self.left_label_frame.grid_rowconfigure(0, weight=1)
        self.current_refrigerator_food_label_left = Label(
            self.left_label_frame,
            anchor="n",
            font=Program.Program.resizing_pantry_font,
            justify=LEFT,
        )
        self.current_refrigerator_food_label_left.bind(
            "<Button-1>",
            lambda _: Program.Program.controller.change_frames(In_refrigerator_frame),
        )
        self.current_refrigerator_food_label_left.grid(row=0, column=0, sticky="nw")
        self.current_refrigerator_food_label_right = Label(
            self.left_label_frame,
            anchor="n",
            font=Program.Program.resizing_pantry_font,
            justify=LEFT,
        )
        self.current_refrigerator_food_label_right.bind(
            "<Button-1>",
            lambda _: Program.Program.controller.change_frames(In_refrigerator_frame),
        )
        self.current_refrigerator_food_label_right.grid(row=0, column=1, sticky="nw")
        self.current_refrigerator_food_label_right.grid_remove()

        self.cabinet_food_label = Label(
            self.right_frame, text="Cabinet Food", font=Program.Program.resizing_title_font
        )
        self.cabinet_food_label.bind(
            "<Button-1>", lambda _: Program.Program.controller.change_frames(In_cabinet_frame)
        )
        self.cabinet_food_label.pack(fill="x")
        self.right_label_frame = Frame(self.right_frame)
        self.right_label_frame.pack(fill="both", expand=True)
        self.right_label_frame.bind(
            "<Button-1>", lambda _: Program.Program.controller.change_frames(In_cabinet_frame)
        )
        self.right_label_frame.grid_rowconfigure(0, weight=1)
        self.current_cabinet_food_label_left = Label(
            self.right_label_frame,
            anchor="n",
            font=Program.Program.resizing_pantry_font,
            justify=LEFT,
        )
        self.current_cabinet_food_label_left.bind(
            "<Button-1>", lambda _: Program.Program.controller.change_frames(In_cabinet_frame)
        )
        self.current_cabinet_food_label_left.grid(row=0, column=0, sticky="nw")
        self.current_cabinet_food_label_right = Label(
            self.right_label_frame,
            anchor="n",
            font=Program.Program.resizing_pantry_font,
            justify=LEFT,
        )
        self.current_cabinet_food_label_right.bind(
            "<Button-1>", lambda _: Program.Program.controller.change_frames(In_cabinet_frame)
        )
        self.current_cabinet_food_label_right.grid(row=0, column=1, sticky="nw")
        self.current_cabinet_food_label_right.grid_remove()

        self.edit_ingredient_button = Button(
            self,
            text="Edit Ingredient",
            command=lambda: self.edit_ingredient_clicked(
                self.ingredients_combo_box.get().capitalize()
            ),
        )
        self.combo_box_style = ttk.Style()
        self.combo_box_style.theme_use("alt")
        self.edit_ingredient_button.grid(row=3, column=0, pady=(0, 45))
        self.ingredients_combo_box = ttk.Combobox(
            self,
            width=27,
            values=sorted(list(Ingredient.ingredients_dict.keys())),
            height=4,
            style="colored.TCombobox",
        )
        self.ingredients_combo_box_clicked = False
        self.ingredients_combo_box.set("Select Ingredient")
        self.ingredients_combo_box.bind(
            "<KeyRelease>",
            lambda event: self.update_combo_box_ingredients(event),
        )
        self.ingredients_combo_box.bind(
            "<Button-1>",
            lambda event: (
                Program.Program.controller.default_combo_value_clear(
                    self.ingredients_combo_box, "Select Ingredient"
                ),
                self.ingredients_combo_box_clicked_event(),
            )
            if not self.ingredients_combo_box_clicked
            else None,
        )
        self.ingredients_combo_box.bind(
            "<<ComboboxSelected>>",
            lambda event: self.update_combo_box_ingredients(),
        )
        self.ingredients_combo_box.grid(row=2, column=0)

    def change_colors(self, bg_color, primary_color, primary_variant):
        elevation_1_color = Program.Program.convert_rgb_to_hex(
            Program.Program.overlay_colors(
                Program.Program.convert_hex_to_rgb(bg_color), (255, 255, 255), 0.05
            )
        )
        if Program.Program.light_mode:
            button_text_color = "#FFFFFF"
            label_color = Program.Program.convert_rgb_to_hex(
                Program.Program.overlay_colors(
                    Program.Program.convert_hex_to_rgb(elevation_1_color), (0, 0, 0), 0.87
                )
            )
        else:
            button_text_color = "#000000"
            label_color = Program.Program.convert_rgb_to_hex(
                Program.Program.overlay_colors(
                    Program.Program.convert_hex_to_rgb(elevation_1_color), (255, 255, 255), 0.87
                )
            )

        self["bg"] = bg_color
        self.middle_frame["bg"] = bg_color
        self.lower_frame["bg"] = bg_color
        self.label_title.config(bg=elevation_1_color, fg=label_color)
        self.left_frame["bg"] = elevation_1_color
        self.right_frame["bg"] = elevation_1_color
        self.left_label_frame["bg"] = elevation_1_color
        self.right_label_frame["bg"] = elevation_1_color
        self.refrigerator_food_label.config(bg=elevation_1_color, fg=label_color)
        self.cabinet_food_label.config(bg=elevation_1_color, fg=label_color)
        self.current_refrigerator_food_label_left.config(
            bg=elevation_1_color, fg=label_color
        )
        self.current_refrigerator_food_label_right.config(
            bg=elevation_1_color, fg=label_color
        )
        self.current_cabinet_food_label_left.config(
            bg=elevation_1_color, fg=label_color
        )
        self.current_cabinet_food_label_right.config(
            bg=elevation_1_color, fg=label_color
        )

        self.combo_box_style.map(
            "colored.TCombobox", fieldbackground=[("readonly", elevation_1_color)]
        )
        self.combo_box_style.configure(
            "colored.TCombobox",
            foreground=label_color,
            fieldbackground=elevation_1_color,
            background=primary_color,
            insertcolor=label_color,
            arrowcolor=button_text_color,
        )
        self.ingredients_combo_box.tk.eval(
            f"[ttk::combobox::PopdownWindow %s].f.l configure -foreground {label_color} -background {elevation_1_color}"
            % self.ingredients_combo_box
        )
        self.edit_ingredient_button_image = Program.Program.create_rounded_button_image(
            bg_color,
            primary_color,
            Program.Program.convert_rgb_to_hex(
                Program.Program.overlay_colors(
                    Program.Program.convert_hex_to_rgb(primary_color),
                    Program.Program.convert_hex_to_rgb(button_text_color),
                    0.87,
                )
            ),
            "Edit Ingredient",
            self.edit_ingredient_button.winfo_width(),
            self.edit_ingredient_button.winfo_height(),
            22,
        )
        self.edit_ingredient_button.config(
            border="0",
            relief="flat",
            borderwidth=0,
            highlightthickness=0,
            activebackground=bg_color,
            image=self.edit_ingredient_button_image,
        )

        self.my_pantry_tab_button_image = Program.Program.create_rounded_button_image(
            bg_color,
            primary_color,
            Program.Program.convert_rgb_to_hex(
                Program.Program.overlay_colors(
                    Program.Program.convert_hex_to_rgb(primary_color),
                    Program.Program.convert_hex_to_rgb(button_text_color),
                    0.38,
                )
            ),
            "My Pantry",
            self.my_pantry_tab_button.winfo_width(),
            self.my_pantry_tab_button.winfo_height(),
            22,
        )
        self.my_pantry_tab_button.config(
            border="0",
            relief="sunken",
            borderwidth=0,
            highlightthickness=0,
            activebackground=bg_color,
            background=bg_color,
            state="normal",
            image=self.my_pantry_tab_button_image,
        )

        self.recipes_tab_button_image = Program.Program.create_rounded_button_image(
            bg_color,
            primary_color,
            Program.Program.convert_rgb_to_hex(
                Program.Program.overlay_colors(
                    Program.Program.convert_hex_to_rgb(primary_color),
                    Program.Program.convert_hex_to_rgb(button_text_color),
                    0.87,
                )
            ),
            "Recipes",
            self.my_pantry_tab_button.winfo_width(),
            self.my_pantry_tab_button.winfo_height(),
            22,
        )
        self.recipes_tab_button.config(
            border="0",
            relief="flat",
            borderwidth=0,
            highlightthickness=0,
            activebackground=bg_color,
            image=self.recipes_tab_button_image,
        )

    def ingredients_combo_box_clicked_event(self):
        self.ingredients_combo_box_clicked = True

    def update_labels(self):
        self.current_refrigerator_food_label_right.grid_remove()
        self.current_cabinet_food_label_right.grid_remove()
        self.left_label_frame.grid_columnconfigure(0, weight=0)
        self.left_label_frame.grid_columnconfigure(1, weight=0)
        self.right_label_frame.grid_columnconfigure(0, weight=0)
        self.right_label_frame.grid_columnconfigure(1, weight=0)
        self.current_refrigerator_food_label_left.config(
            wraplength=self.left_label_frame.winfo_width()
        )
        self.current_cabinet_food_label_left.config(
            wraplength=self.right_label_frame.winfo_width()
        )
        refrigerator_height = int(
            self.left_label_frame.winfo_height()
            / Program.Program.resizing_pantry_font.metrics("linespace")
        )
        cabinet_height = int(
            self.right_label_frame.winfo_height()
            / Program.Program.resizing_pantry_font.metrics("linespace")
        )
        self.current_refrigerator_food_label_left["text"] = (
            "\n".join(
                [
                    "-" + ingredient
                    for ingredient in In_refrigerator.refrigerator_list[
                        0:refrigerator_height
                    ]
                ]
            )
            + "\n"
        )
        self.current_cabinet_food_label_left["text"] = (
            "\n".join(
                [
                    "-" + ingredient
                    for ingredient in In_cabinet.cabinet_list[0:cabinet_height]
                ]
            )
            + "\n"
        )
        self.current_refrigerator_food_label_left.update_idletasks()
        self.current_cabinet_food_label_left.update_idletasks()
        if (
            2 * self.current_refrigerator_food_label_left.winfo_width()
            < self.left_label_frame.winfo_width()
        ):
            self.current_refrigerator_food_label_right.config(
                wraplength=self.left_frame.winfo_width() // 2
            )
            self.current_refrigerator_food_label_right["text"] = (
                "\n".join(
                    [
                        "-" + ingredient
                        for ingredient in In_refrigerator.refrigerator_list[
                            refrigerator_height : 2 * refrigerator_height + 1
                        ]
                    ]
                )
                + "\n"
            )
            self.current_refrigerator_food_label_right.grid()
            self.left_label_frame.grid_columnconfigure(0, weight=1)
            self.left_label_frame.grid_columnconfigure(1, weight=1)
        else:
            self.left_label_frame.grid_columnconfigure(0, weight=0)
            self.left_label_frame.grid_columnconfigure(1, weight=0)
        if (
            2 * self.current_cabinet_food_label_left.winfo_width()
            < self.right_label_frame.winfo_width()
        ):
            self.current_cabinet_food_label_right.config(
                wraplength=self.right_frame.winfo_width() // 2
            )
            self.current_cabinet_food_label_right["text"] = (
                "\n".join(
                    [
                        "-" + ingredient
                        for ingredient in In_cabinet.cabinet_list[
                            cabinet_height : 2 * cabinet_height + 1
                        ]
                    ]
                )
                + "\n"
            )
            self.current_cabinet_food_label_right.grid()
            self.right_label_frame.grid_columnconfigure(0, weight=1)
            self.right_label_frame.grid_columnconfigure(1, weight=1)
        else:
            self.right_label_frame.grid_columnconfigure(0, weight=0)
            self.right_label_frame.grid_columnconfigure(1, weight=0)

    def edit_ingredient_clicked(self, text_in_combobox):
        if (
            not self.ingredients_combo_box_clicked
            and text_in_combobox == "Select ingredient"
        ):
            text_in_combobox = ""
        search = Program.Program.search_ingredient_name(text_in_combobox)
        if search != None:
            Program.Program.controller.frames[Edit_ingredient].update_frame(text_in_combobox)

    def update_combo_box_ingredients(self, event=""):
        search_string = self.ingredients_combo_box.get().upper()
        if (
            not self.ingredients_combo_box_clicked
            and search_string == "SELECT INGREDIENT"
        ):
            search_string = ""

        found_ingredients_dict = {}
        for ingredient_name in Ingredient.ingredients_dict:
            indx = ingredient_name.upper().find(search_string)
            if indx != -1:
                found_ingredients_dict.setdefault(indx, list())
                found_ingredients_dict[indx].append(ingredient_name)
        self.ingredients_based_on_search_list = []
        for key in sorted(tuple(found_ingredients_dict.keys())):
            self.ingredients_based_on_search_list += sorted(found_ingredients_dict[key])
        self.ingredients_combo_box["values"] = self.ingredients_based_on_search_list